/********************************************
 * 功能说明: 平台校验工程类
 * 模块名称: 校验模块
 * 系统名称: java敏捷开发平台
 * 软件版权:
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2017年5月12日 上午11:38:29
 * 审核人员:
 * 相关文档:
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.validator;

import com.hyacinth.utils.DateUtils;
import com.hyacinth.utils.StringUtils;
import com.hyacinth.validator.annotation.FieldMeta;

import javax.validation.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


/**
 * 平台校验工程类
 * @author zhangfb
 * @version 1.0.0.1
 */
public class JadpValidatorFactory {

	private static Validator validator; // 它是线程安全的
	private static Map<Class<?>, Map<String, String>> classFieldMetaMap = new HashMap<Class<?>, Map<String, String>>();
	
	static {
		ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
		validator = factory.getValidator();
	}

	public static <T> void validate(T t) {
		// 注解解析
		analyBase(t);
		Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
		if (constraintViolations.size() > 0) {
			for (ConstraintViolation<T> constraintViolation : constraintViolations) {
				String fName = getFieldMeta(t.getClass(), constraintViolation.getPropertyPath().toString());
				throw new ValidationException(fName + constraintViolation.getMessage());
			}
		}
	}
	
	private static String getFieldMeta(Class<?> type, String name) {
		Map<String, String> fieldMetaMap = classFieldMetaMap.get(type);
		if (fieldMetaMap == null) {
			fieldMetaMap = new HashMap<String, String>();
			Field[] fields = type.getDeclaredFields();
			for (Field f : fields) {
				FieldMeta fm = f.getAnnotation(FieldMeta.class);
				if (fm != null && !fm.name().isEmpty()) {
					fieldMetaMap.put(f.getName(), fm.name());
				} else if (fm != null && !fm.param().isEmpty()) {
					fieldMetaMap.put(f.getName(), fm.param());
				} else {
					fieldMetaMap.put(f.getName(), f.getName());
				}
			}
			classFieldMetaMap.put(type, fieldMetaMap);
		}
		return fieldMetaMap.get(name);
	}

	/**
	 * 注解解析
	 */
	private static <T> void analyBase(T t) {
		if (t == null) {
			throw new RuntimeException("The original object cannot be empty");
		}
		Field[] fields = t.getClass().getDeclaredFields();
		for (Field f : fields) {
			try {
				FieldMeta fm = f.getAnnotation(FieldMeta.class);
				if (fm == null) {
					continue;
				}
				f.setAccessible(true);
				String filedVal = String.valueOf(f.get(t)); //字段值
				String fmVal = fm.value(); //注解默认值
				if (!fmVal.isEmpty() && (StringUtils.isBlank(filedVal) || "null".equals(filedVal))) {
					if (f.getType() == fmVal.getClass()) {
						f.set(t, fmVal);
					} else {
						if (f.getType() == String.class) {
							f.set(t, fmVal);
						} else if (f.getType() == Long.class) {
							f.set(t, new Long(fmVal));
						} else if (f.getType() == BigDecimal.class) {
							f.set(t, new BigDecimal(fmVal));
						} else if (f.getType() == Integer.class) {
							f.set(t, new Integer(fmVal));
						} else if (f.getType() == Double.class) {
							f.set(t, new Double(fmVal));
						} else if (f.getType() == Date.class) {
							f.set(t, DateUtils.parse(fmVal));
						} else {
							f.set(t, fmVal);
						}
					}
				}
			} catch (IllegalAccessException e) {
				throw new RuntimeException("The original object parses the exception", e);
			}
		}
	}

}
